home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / libsst.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-25  |  10.7 KB  |  506 lines

  1. /* libsst.c - SPARC sound tools library
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11.  
  12. ** Hacked on by jwz for emacs.
  13.  
  14. */
  15.  
  16. /* Synched up with: Not in FSF. */
  17.  
  18. #ifdef emacs
  19. #include <config.h>
  20. #include "lisp.h"
  21. #else
  22. #if __STDC__ || defined(STDC_HEADERS)
  23. #include <stdlib.h>
  24. #include <unistd.h>
  25. #endif
  26. #include <stdio.h>
  27. #endif
  28. #include <fcntl.h>
  29. #include "libsst.h"
  30.  
  31. #define AUDBUF 1024
  32.  
  33. extern void usleep();
  34.  
  35. int
  36. sst_open(play_level, record_level)
  37.     int play_level, record_level;
  38.     {
  39.     int fd, i, gr, ger, gx;
  40.     struct audio_ioctl ai;
  41.     char *getenv(), *ep;
  42.  
  43.     fd = open( "/dev/audio", O_RDWR );
  44.     if ( fd < 0 )
  45.     {
  46.     perror( "sst_open: open /dev/audio" );
  47.     return( fd );
  48.     }
  49.  
  50. #ifdef AUDIOSETQSIZE /* This no longer exists as of 4.1.2. */
  51.  
  52.     /* Shrink audio device's queue size, to cut down time delay. */
  53.     i = AUDBUF;
  54.     if ( ioctl( fd, AUDIOSETQSIZE, &i ) < 0 )
  55.     {
  56.     perror( "sst_open: SETQSIZE" );
  57.     return( fd );
  58.     }
  59. #endif /* AUDIOSETQSIZE */
  60.  
  61.     /* Set gains.  -10 <= ger <= 18,  -18 <= gr <= 12,  -18 <= gx <= 12. */
  62.     if (!play_level) 
  63.     {
  64.     play_level = 75;
  65.     if ( (ep = getenv( "SST_PLAY" )) != NULL )
  66.     {
  67.         play_level = atoi( ep );
  68.         if ( play_level < 0 || play_level > 99 )
  69.         {
  70.         warn( "sst_open: SST_PLAY must be between 0 and 99" );
  71.         return( -1 );
  72.         }
  73.     }
  74.     }
  75.     if (!record_level) 
  76.     {
  77.     record_level = 75;
  78.     if ( (ep = getenv( "SST_RECORD" )) != NULL )
  79.     {
  80.         record_level = atoi( ep );
  81.         if ( record_level < 0 || record_level > 99 )
  82.         {
  83.         warn( "sst_open: SST_RECORD must be between 0 and 99" );
  84.         return( -1 );
  85.         }
  86.     }
  87.     }
  88.  
  89.     play_level = play_level * 59 / 100 - 28;
  90.     ger = play_level / 2;
  91.     gr = play_level - ger;
  92.     if ( ger < -10 )
  93.     {
  94.     ger = -10;
  95.     gr = play_level - ger;
  96.     }
  97.     if ( gr > 12 )
  98.     {
  99.     gr = 12;
  100.     ger = play_level - gr;
  101.     }
  102.     gx = record_level * 31 / 100 - 18;
  103.     sst_set_gr( fd, gr );
  104.     sst_set_ger( fd, ger );
  105.     sst_set_gx( fd, gx );
  106.  
  107.     /*  Initialize the MMR2 register to send the output to either
  108.     **  the speaker or the earphone jack, depending on SST_EARPHONES.
  109.     */
  110.     ai.control = AUDIO_MAP_MMR2;
  111.     if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
  112.     {
  113.     perror( "sst_open: GETREG MMR2" );
  114.     return( -1 );
  115.     }
  116.     if ( (ep = getenv( "SST_EARPHONES" )) != NULL )
  117.     ai.data[0] &= ~AUDIO_MMR2_BITS_LS;
  118.     else
  119.     ai.data[0] |= AUDIO_MMR2_BITS_LS;
  120.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  121.     {
  122.     perror( "sst_open: SETREG MMR2" );
  123.     return( fd );
  124.     }
  125.  
  126.     return fd;
  127.     }
  128.  
  129. void
  130. sst_close( fd )
  131. int fd;
  132.     {
  133.     struct audio_ioctl ai;
  134.  
  135.     ai.control = AUDIO_MAP_MMR1;
  136.     ai.data[0] = 0;
  137.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  138.     {
  139.     perror( "sst_close: SETREG MMR1" );
  140.     }
  141.     ai.control = AUDIO_MAP_MMR2;
  142.     ai.data[0] = 0;
  143.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  144.     {
  145.     perror( "sst_close: SETREG MMR2" );
  146.     }
  147.     close( fd );
  148.     }
  149.  
  150. /* These are tables of values to be loaded into various gain registers.
  151. */
  152.  
  153. static unsigned char ger_table[][2] = {
  154.     0xaa,    0xaa,    /* -10db */
  155.     0x79,    0xac,
  156.     0x41,    0x99,
  157.     0x9c,    0xde,
  158.     0x74,    0x9c,    /* -6db */
  159.     0x6a,    0xae,
  160.     0xab,    0xdf,
  161.     0x64,    0xab,
  162.     0x2a,    0xbd,
  163.     0x5c,    0xce,
  164.     0x00,    0x99,    /* 0db */
  165.     0x43,    0xdd,
  166.     0x52,    0xef,
  167.     0x55,    0x42,
  168.     0x31,    0xdd,
  169.     0x43,    0x1f,
  170.     0x40,    0xdd,    /* 6db */
  171.     0x44,    0x0f,
  172.     0x31,    0x1f,
  173.     0x10,    0xdd,
  174.     0x41,    0x0f,
  175.     0x60,    0x0b,
  176.     0x42,    0x10,    /* 12db */
  177.     0x11,    0x0f,
  178.     0x72,    0x00,
  179.     0x21,    0x10,
  180.     0x22,    0x00,
  181.     0x00,    0x0b,
  182.     0x00,    0x0f,    /* 18db */
  183.     };
  184.  
  185.  
  186. static unsigned char gr_gx_table[][2] = {
  187.     0x8b,    0x7c,    /* -18db */
  188.     0x8b,    0x35,
  189.     0x8b,    0x24,
  190.     0x91,    0x23,
  191.     0x91,    0x2a,
  192.     0x91,    0x3b,
  193.     0x91,    0xf9,    /* -12db */
  194.     0x91,    0xb6,
  195.     0x91,    0xa4,
  196.     0x92,    0x32,
  197.     0x92,    0xaa,
  198.     0x93,    0xb3,
  199.     0x9f,    0x91,    /* -6db */
  200.     0x9b,    0xf9,
  201.     0x9a,    0x4a,
  202.     0xa2,    0xa2,
  203.     0xaa,    0xa3,
  204.     0xbb,    0x52,
  205.     0x08,    0x08,    /* 0db */
  206.     0x3d,    0xac,
  207.     0x25,    0x33,
  208.     0x21,    0x22,
  209.     0x12,    0xa2,
  210.     0x11,    0x3b,
  211.     0x10,    0xf2,    /* 6db */
  212.     0x02,    0xca,
  213.     0x01,    0x5a,
  214.     0x01,    0x12,
  215.     0x00,    0x32,
  216.     0x00,    0x13,
  217.     0x00,    0x0e,    /* 12db */
  218.     };
  219.  
  220. void
  221. sst_set_ger( fd, value )
  222. int fd, value;
  223.     {
  224.     struct audio_ioctl ai;
  225.  
  226.     if ( ( value < -10 ) || ( value > 18 ) )
  227.     {
  228.       char buf [255];
  229.       sprintf (buf, "sst_set_ger: GER %d out of range", value);
  230.       warn(buf);
  231.       return;
  232.     }
  233.  
  234.     /*  Add 10 to the value to get the index into the table.  */
  235.     ai.control = AUDIO_MAP_GER;
  236.     ai.data[0] = ger_table[value + 10][1];
  237.     ai.data[1] = ger_table[value + 10][0];
  238.  
  239.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  240.     {
  241.     perror( "sst_set_ger: SETREG GER" );
  242.     }
  243.  
  244.     ai.control = AUDIO_MAP_MMR1;
  245.     if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
  246.     {
  247.     perror( "sst_set_ger: GETREG MMR1" );
  248.     }
  249.     ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GER;
  250.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  251.     {
  252.     perror( "sst_set_ger: SETREG MMR1" );
  253.     }
  254.     }
  255.  
  256. void
  257. sst_set_gr( fd, value )
  258. int fd, value;
  259.     {
  260.     struct audio_ioctl ai;
  261.  
  262.     if ( ( value < -18 ) || ( value > 12 ) )
  263.     {
  264.       char buf [255];
  265.       sprintf (buf,  "sst_set_gr: GR %d out of range", value);
  266.       warn (buf);
  267.       return;
  268.     }
  269.  
  270.     ai.control = AUDIO_MAP_GR;
  271.     ai.data[0] = gr_gx_table[value + 18][1];
  272.     ai.data[1] = gr_gx_table[value + 18][0];
  273.  
  274.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  275.     {
  276.     perror( "sst_set_gr: SETREG GR" );
  277.     }
  278.  
  279.     ai.control = AUDIO_MAP_MMR1;
  280.     if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
  281.     {
  282.     perror( "sst_set_gr: GETREG MMR1" );
  283.     }
  284.     ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GR;
  285.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  286.     {
  287.     perror( "sst_set_gr: SETREG MMR1" );
  288.     }
  289.     }
  290.  
  291. void
  292. sst_set_gx( fd, value )
  293. int fd, value;
  294.     {
  295.     struct audio_ioctl ai;
  296.     char buf [255];
  297.  
  298.     if ( ( value < -18 ) || ( value > 12 ) )
  299.     {
  300.       sprintf (buf, "sst_set_gx: GX %d out of range", value);
  301.       warn (buf);
  302.       return;
  303.     }
  304.  
  305.     /*  We add 18 to get the index into the table, since entry 0 represents
  306.     *  -18db.
  307.     */
  308.     ai.control = AUDIO_MAP_GX;
  309.     ai.data[0] = gr_gx_table[value + 18][1];
  310.     ai.data[1] = gr_gx_table[value + 18][0];
  311.  
  312.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  313.     {
  314.     perror( "sst_set_gx: SETREG GX" );
  315.     }
  316.  
  317.     ai.control = AUDIO_MAP_MMR1;
  318.     if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
  319.     {
  320.     perror( "sst_set_gx: GETREG MMR1" );
  321.     }
  322.     ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GX;
  323.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  324.     {
  325.     perror( "sst_set_gx: SETREG MMR1" );
  326.     }
  327.     }
  328.  
  329. void
  330. sst_tones( fd, dhz1, dhz2, thz, rhz, usec )
  331. int fd, dhz1, dhz2, thz, rhz, usec;
  332.     {
  333.     char buf [255];
  334.     struct audio_ioctl ai;
  335.     int dval1, dval2, tval, rval;
  336.     unsigned char oldmmr2, newmmr2;
  337.  
  338.     if ( dhz1 == 0 )
  339.     dval1 = 0;
  340.     else
  341.     {
  342.     dval1 = ( dhz1 * 128 + 63 ) / 1000;
  343.     if ( ( dval1 < 1 ) || ( dval1 > 255 ) )
  344.         {
  345.           sprintf(buf, "sst_tones: dhz1 %d out of range", dhz1 );
  346.           warn (buf);
  347.           return;
  348.         }
  349.     }
  350.  
  351.     if ( dhz2 == 0 )
  352.     dval2 = 0;
  353.     else
  354.     {
  355.     dval2 = ( dhz2 * 128 + 63 ) / 1000;
  356.     if ( ( dval2 < 1 ) || ( dval2 > 255 ) )
  357.         {
  358.           sprintf(buf, "sst_tones: dhz2 %d out of range", dhz2 );
  359.           warn (buf);
  360.           return;
  361.         }
  362.     }
  363.  
  364.     if ( thz == 0 )
  365.     tval = 0;
  366.     else
  367.     {
  368.     tval = ( thz * 128 + 63 ) / 2000;
  369.     if ( ( tval < 1 ) || ( tval > 255 ) )
  370.         {
  371.           sprintf(buf, "sst_tones: thz %d out of range", thz );
  372.           warn (buf);
  373.           return;
  374.         }
  375.     }
  376.  
  377.     if ( rhz == 0 )
  378.     rval = 0;
  379.     else
  380.     {
  381.     rval = ( rhz * 128 + 63 ) / 2000;
  382.     if ( ( rval < 1 ) || ( rval > 255 ) )
  383.         {
  384.           sprintf(buf, "sst_tones: rhz %d out of range", dhz2 );
  385.           warn (buf);
  386.           return;
  387.         }
  388.     }
  389.  
  390.     if ( ( dval1 != 0 || dval2 != 0 ) && ( tval != 0 || rval != 0 ) )
  391.     {
  392.       sprintf(buf, "sst_tones: cannot use DTMF and TONE or RINGER at the same time", dhz2 );
  393.       warn (buf);
  394.       return;
  395.     }
  396.  
  397.     if ( tval != 0 && rval != 0 )
  398.     {
  399.       sprintf(buf, "sst_tones: cannot use TONE and RINGER at the same time", dhz2 );
  400.       warn (buf);
  401.     return;
  402.     }
  403.  
  404.     ai.control = AUDIO_MAP_MMR2;
  405.     if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
  406.     {
  407.     perror( "sst_tones: GETREG MMR2" );
  408.     }
  409.     oldmmr2 = newmmr2 = ai.data[0];
  410.  
  411.     if ( dval1 != 0 || dval2 != 0 )
  412.     {
  413.     newmmr2 |= AUDIO_MMR2_BITS_DTMF;
  414.     ai.control = AUDIO_MAP_FTGR;
  415.     ai.data[0] = dval1;
  416.     ai.data[1] = dval2;
  417.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  418.         {
  419.         perror( "sst_tones: SETREG FTGR" );
  420.         }
  421.     }
  422.  
  423.     if ( tval != 0 )
  424.     {
  425.     newmmr2 |= AUDIO_MMR2_BITS_TONE;
  426.     ai.control = AUDIO_MAP_FTGR;
  427.     ai.data[0] = tval;
  428.     ai.data[1] = 0;
  429.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  430.         {
  431.         perror( "sst_tones: SETREG FTGR" );
  432.         }
  433.     }
  434.  
  435.     if ( rval != 0 )
  436.     {
  437.     newmmr2 |= AUDIO_MMR2_BITS_RINGER;
  438.     ai.control = AUDIO_MAP_FTGR;
  439.     ai.data[0] = rval;
  440.     ai.data[1] = 0;
  441.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  442.         {
  443.         perror( "sst_tones: SETREG FTGR" );
  444.         }
  445.     }
  446.  
  447.     ai.control = AUDIO_MAP_MMR2;
  448.     ai.data[0] = newmmr2;
  449.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  450.     {
  451.     perror( "sst_tones: SETREG MMR2" );
  452.     }
  453.  
  454.     usleep( usec );
  455.  
  456.     ai.data[0] = oldmmr2;
  457.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  458.     {
  459.     perror( "sst_tones: SETREG MMR2" );
  460.     }
  461.     }
  462.  
  463. void
  464. sst_dtmf( fd, dial, usecper, usecpause )
  465. int fd, usecper, usecpause;
  466. char *dial;
  467.     {
  468.     char *cp;
  469.  
  470.     for ( cp = dial; *cp != '\0'; cp++ )
  471.     {
  472.     switch ( *cp )
  473.         {
  474.         case '1': sst_tones( fd, 703, 1211, 0, 0, usecper ); break;
  475.         case '2': sst_tones( fd, 703, 1336, 0, 0, usecper ); break;
  476.         case '3': sst_tones( fd, 703, 1492, 0, 0, usecper ); break;
  477.         case 'A': sst_tones( fd, 703, 1648, 0, 0, usecper ); break;
  478.         case '4': sst_tones( fd, 773, 1211, 0, 0, usecper ); break;
  479.         case '5': sst_tones( fd, 773, 1336, 0, 0, usecper ); break;
  480.         case '6': sst_tones( fd, 773, 1492, 0, 0, usecper ); break;
  481.         case 'B': sst_tones( fd, 773, 1648, 0, 0, usecper ); break;
  482.         case '7': sst_tones( fd, 859, 1211, 0, 0, usecper ); break;
  483.         case '8': sst_tones( fd, 859, 1336, 0, 0, usecper ); break;
  484.         case '9': sst_tones( fd, 859, 1492, 0, 0, usecper ); break;
  485.         case 'C': sst_tones( fd, 859, 1648, 0, 0, usecper ); break;
  486.         case '*': sst_tones( fd, 945, 1211, 0, 0, usecper ); break;
  487.         case '0': sst_tones( fd, 945, 1336, 0, 0, usecper ); break;
  488.         case '#': sst_tones( fd, 945, 1492, 0, 0, usecper ); break;
  489.         case 'D': sst_tones( fd, 945, 1648, 0, 0, usecper ); break;
  490.  
  491.         case ' ': case '-': case '(': case ')': case '+':
  492.         continue;    /* ignore */
  493.  
  494.         case ',': usleep( usecper ); break;    /* big pause */
  495.  
  496.         default:
  497.           {
  498.         char buf [255];
  499.         sprintf( buf, "sst_dtmf: unknown dialing code '%c'", *cp );
  500.         warn (buf);
  501.           }
  502.         }
  503.     usleep( usecpause );
  504.     }
  505.     }
  506.